package com.example.shop.rabbitmq.comsumer;

import com.example.shop.mapper.OrderMapper;
import com.example.shop.order.enums.OrderState;
import com.example.shop.rabbitmq.component.OrderComponents;
import com.example.shop.rabbitmq.dto.NoPayOrder;
import com.example.shop.redis.enums.RedisKey;
import com.example.shop.redis.service.LettuceClient;
import com.rabbitmq.client.Channel;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.Arrays;

@Component
public class NoPayDeadOrderConsumer {

    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private LettuceClient redisClient;
    @Autowired
    private RabbitTemplate rabbitTemplate;

    @RabbitListener(queues = {OrderComponents.NO_PAY_DEAD_QUEUE},ackMode = "MANUAL")
    public void noPayDeadConsumer(NoPayOrder noPayOrder, Message message, Channel channel) throws IOException {
        Long goodsId =  noPayOrder.getOrder().getGoodsId();
        String buyGoodsClass = noPayOrder.getOrder().getUserPurchasedGoodsClass();
        int buyNum = noPayOrder.getOrder().getUserPurchasedNumber();
        //归还库存
        StringBuilder scriptStrBuilder = new StringBuilder();
        scriptStrBuilder
                .append("local nowInventory = redis.call('HGET',KEYS[1],field);")
                .append("if nowInventory or redis.call('EXISTS',KEYS[2]) == 1 then ")
                .append("return -1;")
                .append("end")
                .append("local field = string.sub(ARGV[1],2,string.len(ARGV[1])-1);")
                .append("local buyNum = ARGV[2];")
                .append("local surplus = nowInventory + buyNum;")
                .append("return redis.call('HSET',KEYS[1],field,surplus);")
                .append("end ");
        //lua并不支持Integer类型，所以使用long类型
        DefaultRedisScript<Long> script = new DefaultRedisScript<>(scriptStrBuilder.toString(),Long.class);
        String key1 = RedisKey.HashMap.GOODS_INVENTORY.getKey() + goodsId;
        String key2 = RedisKey.SYNC_ME_INVENTORY.getKey() + goodsId;
        //lua脚本的执行，返回该款式的剩余库存量
        Long surplus = redisClient.execLua(script, Arrays.asList(key1,key2),buyGoodsClass,buyNum);
        if(surplus==-1){
            rabbitTemplate.convertAndSend(OrderComponents.ORDER_EXCHANGE,OrderComponents.NO_PAY_ROUTING_KEY, noPayOrder);
            channel.basicReject(message.getMessageProperties().getDeliveryTag(),true);
            return;
        }
        //将订单的状态修改为取消
        Long orderId = noPayOrder.getOrder().getOrderId();
        orderMapper.updateFieldById("order_state", OrderState.CANCEL_ORDER.getOrderState(),orderId);
        //确认消费该消息
        channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
    }
}
